<?php


namespace models\Business;


use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Service\AccountService;
use models\Service\WithdrawService;
use Yaf\Exception;
use Yaf\Registry;
use ylPay\ylPay;

class AliPay
{
//    const APP_ID = '2015102700040153';
    const APP_ID = '2021001159637030';
//    const SELLER_ID = '2088102119685838';
    const SELLER_ID = '2088731721969746';

    // 转账到支付宝账户、B2C红包、C2C红包所需的app_id
    const TRANSFER_APP_ID = '2021001151673687';
    // 转账到支付宝账户、B2C红包、C2C红包所需的user_id
    const TRANSFER_USER_ID = '2088731721969746';

    static public function asyncWithdraw($withdraw_id, $account, $name, $amount) {
        Registry::get('db_log')->info("发起支付宝提现接口的异步调用。提现订单编号: " . $withdraw_id . "。");
//        return self::withdraw($withdraw_id);
    }

    static public function delayWithdraw($withdraw_id, $account, $name, $amount, $time = 30) {
        Registry::get('db_log')->info("发起支付宝提现接口的延迟调用。提现订单编号: " . $withdraw_id . "。延迟时间:" . $time . "秒");
    }

    static public function queryBalance() {
        try {
            $transfer = new ylPay();
            $transfer->setBaseUrl('https://openapi.alipay.com/gateway.do');
            $transfer->setAppId(self::TRANSFER_APP_ID);
            $transfer->params = [
                // 支付宝的uid，可以在打开支付宝后台后通过network查找到
                'alipay_user_id' => self::TRANSFER_USER_ID,
                'account_type' => 'ACCTRANS_ACCOUNT'
            ];

            // 这是应用私钥 签名用的
            $transfer->setAlipayRsaPrivateKeyPath(Registry::get('config')['alipay']['trans']['cooperation']['private_pem']);
            // 支付宝公钥证书绝对路径
            // alipay.trans.platform.public_pem
            $transfer->setTransferPublicKey(Registry::get('config')['alipay']['trans']['platform']['public_pem']);
            // 设置应用公钥
            $transfer->setAlipayAppCertSn(Registry::get('config')['alipay']['trans']['platform']['app_cert_sn']);
            // 设置根证书
            $transfer->setAlipayTranserRootCertSn(Registry::get('config')['alipay']['trans']['platform']['root_cert_sn']);

            return $transfer->alipay_transfer->alipayFundAccountQuery();
        } catch (\Exception $e) {
            throw $e;
        }
    }

    static public function withdraw($withdraw_id, $account, $name, $amount) {
        Registry::get('db_log')->info("提现订单创建成功.提现订单编号: " . json_encode(func_get_args()) . "。调用单笔转账至支付宝接口");
        try {
            $trans = new ylPay();
            $trans->setBaseUrl('https://openapi.alipay.com/gateway.do');
            $trans->setAppId(self::TRANSFER_APP_ID);
            // 这是应用私钥 签名用的
            $trans->setAlipayRsaPrivateKeyPath(Registry::get('config')['alipay']['trans']['cooperation']['private_pem']);
            // 支付宝公钥证书绝对路径
            $trans->setTransferPublicKey(Registry::get('config')['alipay']['trans']['platform']['public_pem']);
            // 设置应用公钥
            $trans->setAlipayAppCertSn(Registry::get('config')['alipay']['trans']['platform']['app_cert_sn']);
            // 设置根证书
            $trans->setAlipayTranserRootCertSn(Registry::get('config')['alipay']['trans']['platform']['root_cert_sn']);

            $trans->params = [
                // 请求参数 一个json字符串
                'biz_content' => json_encode([
                    // 商户订单号
                    'out_biz_no' => $withdraw_id,
                    // 订单金额
                    'trans_amount' => /*'0.1',*/ $amount,
                    // 业务产品码
                    // 单笔无密转账到支付宝账户固定为: TRANS_ACCOUNT_NO_PWD；
                    // 单笔无密转账到银行卡固定为: TRANS_BANKCARD_NO_PWD;
                    // 收发现金红包固定为: STD_RED_PACKET；
                    'product_code' => 'TRANS_ACCOUNT_NO_PWD',
                    // 	转账业务的标题，用于在支付宝用户的账单里显示
                    'order_title' => '豆子优拼余额提现',
                    'payee_info' => [
                        // 支付宝登录号，支持邮箱和手机号格式: ALIPAY_LOGON_ID
                        // 支付宝的会员ID: ALIPAY_USER_ID
                        'identity' => $account,
                        'identity_type' => 'ALIPAY_LOGON_ID',
                        'name' => $name
                    ],
                    //
                    'business_params' => [
                        // 转账到银行卡的预期到账时间 不传时默认T+1到账 T0表示T+0到账
                        'withdraw_timeliness' => 'T0',
                        // 红包业务必传 取值: REDPACKET
                        // C2C现金红包、B2C现金红包均需传入
                        'sub_biz_scene' => 'REDPACKET'
                    ],
                    'timeout_express' => '15m',
                    'biz_scene' => 'DIRECT_TRANSFER'
                ]),
                // 公共参数
                'notify_url' => '',
                'version' => '1.0',
                'sign_type' => 'RSA2'
            ];

            // 支付宝转账/B2C红包
            $r = $trans->alipay_transfer->alipayFundTransUniTransfer();

            Registry::get('db_log')->info("提现订单结果: " . json_encode($r));

            // 打款成功 修改打款记录状态
//            WithdrawService::getInstance()->update(['stats' => (int)$r['status'] === 'SUCCESS'], $withdraw_id);

            return $r;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * 根据第三方订单编号查询订单状态
     * @param $out_trade_no
     * @return array|null
     */
    static public function QueryWithdraw($out_trade_no) {
        Registry::get('db_log')->info("查询提现订单状态.三方提现订单编号: " . $out_trade_no);
        $trans = new ylPay();
        $trans->setBaseUrl('https://openapi.alipay.com/gateway.do');
        $trans->setAppId(self::TRANSFER_APP_ID);
        // 这是应用私钥 签名用的
        $trans->setAlipayRsaPrivateKeyPath(Registry::get('config')['alipay']['trans']['cooperation']['private_pem']);
        // 支付宝公钥证书绝对路径
        $trans->setTransferPublicKey(Registry::get('config')['alipay']['trans']['platform']['public_pem']);
        // 设置应用公钥
        $trans->setAlipayAppCertSn(Registry::get('config')['alipay']['trans']['platform']['app_cert_sn']);
        // 设置根证书
        $trans->setAlipayTranserRootCertSn(Registry::get('config')['alipay']['trans']['platform']['root_cert_sn']);

        $trans->params = [
            'order_id' => $out_trade_no,
            'product_code' => 'TRANS_ACCOUNT_NO_PWD',
            'version' => '1.0',
            'sign_type' => 'RSA2',
        ];
        $res = $trans->alipay_transfer->alipayFundTransCommonQuery();

        if ($res['order_id'] == $out_trade_no && isset($res['status']))
            return ['stats' => $res['status'] === 'SUCCESS' ? 3 : 4];

        return null;
    }

    /**
     * app支付
     * @param array $booking_data
     * @return mixed
     */
    static public function alipayTradeAppPay($booking_data = []) {
        $pay = new ylPay();
        $pay->setBaseUrl('https://openapi.alipay.com/gateway.do');
        $pay->setAppId(self::APP_ID);
        $pay->setAlipayRsaPrivateKeyPath(Registry::get('config')['alipay']['cooperation']['private_pem']);
        $pay->setAlipayRsaPublicKeyPath(Registry::get('config')['alipay']['platform']['public_pem']);

        $pay->params = [
            // 请求参数 一个json字符串
            'biz_content' => json_encode([
                // 商品标题
                'subject' => $booking_data['title'],
                // 商户订单号
                'out_trade_no' => $booking_data['sn'],
                // 订单金额
                'total_amount' => $booking_data['price'],
                // 用户若退出的跳转网址
                'quit_url' => 'http://h5.douziyoupin.com/#/order/list',
                // 销售产品码，商家和支付宝签约的产品码，wap支付的固定值：QUICK_MSECURITY_PAY
                'product_code' => 'QUICK_MSECURITY_PAY',
                /*'goods_detail' => [
                    [
                        // 商品编号
                        'goods_id' => $booking_data['product_id'],
                        // 商品名称
                        'goods_name' => $booking_data['title'],
                        // 商品数量
                        'quantity' => $booking_data['num'],
                        // 商品价格 单位元
                        'price' => $booking_data['price'],
                    ]
                ],*/
                'timeout_express' => ceil((strtotime($booking_data['expired_at']) - time()) / 60) . 'm'
            ]),
            // 公共参数
            'notify_url' => Registry::get('config')['application']['host'] . '/notify/alipay/tradeStatusSync',
            'version' => '1.0',
            'sign_type' => 'RSA2'
        ];

        return $pay->alipay->alipayTradeAppPay();
    }

    /**
     * h5支付宝支付
     * @param array $booking_data
     * @return mixed
     */
    static public function alipayWapPay($booking_data = []) {
        $pay = new ylPay();
        $pay->setBaseUrl('https://openapi.alipay.com/gateway.do');
        $pay->setAppId(self::APP_ID);
        $pay->setAlipayRsaPrivateKeyPath(Registry::get('config')['alipay']['cooperation']['private_pem']);
        $pay->setAlipayRsaPublicKeyPath(Registry::get('config')['alipay']['platform']['public_pem']);

        $pay->params = [
            // 请求参数 一个json字符串
            'biz_content' => json_encode([
                // 商品标题
                'subject' => $booking_data['title'],
                // 商户订单号
                'out_trade_no' => $booking_data['sn'],
                // 订单金额
                'total_amount' => $booking_data['price'],
                // 用户若退出的跳转网址
                'quit_url' => 'http://h5.douziyoupin.com/#/order/list',
                // 销售产品码，商家和支付宝签约的产品码，wap支付的固定值：QUICK_WAP_WAY
                'product_code' => 'QUICK_WAP_WAY',
                // 支付成功后，用户跳转的url
                'return_url' => 'http://douziyoupin.com/conduct',
                /*'goods_detail' => [
                    [
                        // 商品编号
                        'goods_id' => $booking_data['product_id'],
                        // 商品名称
                        'goods_name' => $booking_data['title'],
                        // 商品数量
                        'quantity' => $booking_data['num'],
                        // 商品价格 单位元
                        'price' => $booking_data['price'],
                    ]
                ],*/
                'timeout_express' => ceil((strtotime($booking_data['expired_at']) - time()) / 60) . 'm'
            ]),
            // 公共参数
            'notify_url' => Registry::get('config')['application']['host'] . '/notify/alipay/tradeStatusSync',
            'version' => '1.0',
            'sign_type' => 'RSA2'
        ];

        return $pay->alipay->alipayTradeWapPay();
    }

    /**
     * 支付宝异步回调验签并返回入参
     * @param array $parameters
     * @return mixed
     * @throws Exception
     */
    static public function alipayNotify($parameters = []) {
        // 实例化支付宝sdk，设置app_id、seller_id与支付宝公钥
        $pay = new ylPay();
        $pay->setAppId(self::APP_ID);
        $pay->setAlipaySellerId(self::SELLER_ID);
        $pay->setAlipayRsaPublicKeyPath(Registry::get('config')['alipay']['platform']['public_pem']);

        // 去除参数中的sign与sign_type，并将其他需要验签的参数写入array
        $array = [];
        foreach ($parameters as $key => $val) {
            if ($key == 'sign')
                $pay->setSign($val . '=');
            else if ($key == 'sign_type')
                $pay->setSignType($val);
            else
                $array[$key] = $val;
        }

        // 若待验签为空，抛错。
        // 反之，将待验签的参数设置给支付宝sdk的参数
        if (empty($array))
            throw new Exception("异步回调参数不能为空", 400);
        $pay->params = $array;

        // 返回验签结果
        return $pay->alipay->getAlipayNotifyResponse();
    }
}
